package com.atguigu.study.base;

import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Ticket{
    private int number=50;
//    public synchronized void sale(){
//        if (number>0) {
//            System.out.println(Thread.currentThread().getName()+"卖出了第"+(number--)+"还剩"+number);
//            try {
//                TimeUnit.MILLISECONDS.sleep(200);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//        }
//    }
    private final Lock lock=new ReentrantLock();
    public void sale(){
        lock.lock();
        try {
            if(number>0){
                System.out.println(Thread.currentThread().getName()+"卖出了第"+(number--)+"还剩"+number);
            }
        } finally {
      lock.unlock();
        }
    }
}
public class SaleTicket {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();

//        new Thread(()->{
//            for (int i = 0; i < 50; i++) {
//                ticket.sale();
//            }
//
//        },"张三").start();
//        new Thread(()->{
//            for (int i = 0; i < 50; i++) {
//                ticket.sale();
//            }
//
//        },"李四").start();

//        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
//                Runtime.getRuntime().availableProcessors()+1,
//                                                 1l,
//                                                  TimeUnit.SECONDS,
//                                                     new ArrayBlockingQueue<>(3),
//                                                     Executors.defaultThreadFactory(),
//                                                      new ThreadPoolExecutor.AbortPolicy());
//        ExecutorService executorService = Executors.newFixedThreadPool(3);
//        try {
//            for (int i = 1; i <= 50; i++) {
//                executorService.execute(()->{
//                    ticket.sale();
//                });
//            }
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        } finally {
//            executorService.shutdown();
//        }

//        ExecutorService threadPool = Executors.newFixedThreadPool(3);
//        try {
//            for (int i = 1; i <= 50; i++) {
//                threadPool.execute(()->{
//                    ticket.sale();
//                });
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            threadPool.shutdown();
//        }
//        ExecutorService threadPool = Executors.newFixedThreadPool(3);
//        try {
//            for (int i = 1; i <= 50; i++) {
//                threadPool.execute(()->{
//                    ticket.sale();
//                });
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            threadPool.shutdown();
//        }

        ExecutorService threadPool = Executors.newFixedThreadPool(3);
        try {
            for (int i = 1; i <= 50; i++) {
                threadPool.execute(()->{
                    ticket.sale();
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }

    }
//    java.long.StackOverflowError 栈溢出  error 和Exception 父类为 Throwable
//    java.long.OutOfMemoryError  堆溢出  栈溢出 堆溢出都是错误
    //Exception in thread "main" java.long.OutOfMemoryError: Java heap space
    //GC (分代收集算法) 频繁收集新生代     较少收集老年代    基本不动元空间
    //判断一个对象是不是垃圾 两种方法 根可达 引用计数
}
